package org.digitalsoul.switchplugin.patterns;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.ListIterator;


public class PathMatcher {

    private String currentFolder;
    private List<String> matchedParts;
    private ListIterator<String> patterns;
    private List<String> patternParts;
    private List<String> folderParts;
    private ListIterator<String> folders;
    private String currentPattern;
    
    public boolean match(String path, String pattern) {
        boolean match = false;
        if (path != null && pattern != null) {
            path = normalize(path);
            String[] folders = path.split("/");
            String[] patterns = pattern.split("/");
            if (folders.length > 0 && patterns.length > 0) {
                match = match(folders, patterns);
            }
        }
        return match;
    }

    String normalize(String string) {
//        String[] parts = string.split("/");
//        String lastPart = null;
//        StringBuffer buffer = new StringBuffer();
//        for (int i = 0; i < parts.length; i++) {
//            if (i == 0 && isEmpty(parts[i])) {
//              buffer.append("/");   
//            }
//            else if (!isEmpty(parts[i]) &&
//                (!(parts[i].equals("**") && lastPart.equals("**")))) {
//                buffer.append(parts[i]);
//                buffer.append("/");
//            }
//            lastPart = parts[i];
//        }
//        String path = buffer.toString();
//        path = path.replaceAll("/$", "");
        while (string.matches(".*//.*")) {
            string = string.replaceAll("//", "/");
        }
        while (string.matches(".*\\*\\*/\\*\\*.*")) {
            string = string.replaceAll("\\*\\*/\\*\\*", "**");
        }
        if (!string.equals("/")) {
            string = string.replaceAll("/$", "");
        }
        return string;
    }

    private boolean isEmpty(String string) {
        return (string == null || string.length() == 0);
    }

    private boolean match(String[] folderPartsArray, String[] patternPartsArray) {
        folderParts = Arrays.asList(folderPartsArray);
        matchedParts = new ArrayList<String>();
        patternParts = Arrays.asList(patternPartsArray);
        patterns = patternParts.listIterator();
        folders = folderParts.listIterator();
        currentPattern = patterns.next();
        currentFolder = folders.next();
        do {
            if (currentPattern.equals("**")) {
                
                // spool to next pattern if that is going to match
                if (nextPatternMatches()) {
                    nextPattern();
                }
                else {
                    nextFolder();
                }
            }
            else if (currentPattern.equals("*") || wordsMatch(currentFolder, currentPattern)) {
                nextFolder();
                nextPattern();
            }
            else {
                nextPattern();
            }
        }
        while (currentPattern != null && currentFolder != null);
        return isMatchFulfilled();
    }

    private boolean isMatchFulfilled() {
        return matchedParts.size() == folderParts.size() && !patterns.hasNext() &&
        (currentPattern == null || currentPattern.equals("*") || currentPattern.equals("**"));
    }

    private void nextPattern() {
        currentPattern = patterns.hasNext() ? patterns.next() : null;
    }

    private void nextFolder() {
        matchedParts.add(currentFolder);
        currentFolder = folders.hasNext() ? folders.next() : null;        
    }

    private boolean nextPatternMatches() {
        boolean match = false;
        if (patterns.hasNext()) {
            match = wordsMatch(currentFolder, patterns.next());
            patterns.previous();
        }
        return match;
    }

    private boolean wordsMatch(String folder, String pattern) {
        return folder.matches(pattern);
    }
}
